#!/usr/bin/env python
"""
云打印系统启动脚本
用于启动API服务和打印服务
"""

import os
import sys
import time
import subprocess
import argparse
import signal
import logging
from datetime import datetime

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(f"logs/service_{datetime.now().strftime('%Y%m%d')}.log"),
        logging.StreamHandler()
    ]
)

# 进程列表
processes = []

def setup_environment():
    """设置环境，确保必要的目录存在"""
    # 创建必要的目录
    os.makedirs("logs", exist_ok=True)
    os.makedirs("watch_folder", exist_ok=True)
    os.makedirs("temp_prints", exist_ok=True)
    os.makedirs("print_status", exist_ok=True)
    os.makedirs("static", exist_ok=True)
    
    # 检查配置文件
    if not os.path.exists("config.ini"):
        logging.warning("配置文件不存在，请确保config.ini已正确设置")
        sys.exit(1)

def start_api_server(port=8000):
    """启动API服务器"""
    try:
        logging.info(f"正在启动API服务器，端口: {port}")
        cmd = [sys.executable, "-m", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", str(port)]
        process = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True,
            bufsize=1,
            creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0
        )
        processes.append({"name": "api_server", "process": process, "port": port})
        logging.info(f"API服务器启动成功，进程ID: {process.pid}")
        
        # 输出访问URL
        logging.info(f"API文档地址: http://localhost:{port}/docs")
        logging.info(f"API服务地址: http://localhost:{port}/api")
        logging.info(f"前端页面地址: http://localhost:{port}/static/index.html")
        
        return process
    except Exception as e:
        logging.error(f"启动API服务器失败: {str(e)}")
        return None

def start_print_service():
    """启动打印服务"""
    try:
        logging.info("正在启动打印服务")
        cmd = [sys.executable, "print_service.py"]
        process = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True,
            bufsize=1,
            creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0
        )
        processes.append({"name": "print_service", "process": process})
        logging.info(f"打印服务启动成功，进程ID: {process.pid}")
        return process
    except Exception as e:
        logging.error(f"启动打印服务失败: {str(e)}")
        return None

def monitor_processes():
    """监控进程的输出和状态"""
    try:
        while processes:
            for proc_info in processes:
                process = proc_info["process"]
                name = proc_info["name"]
                
                # 检查进程是否还在运行
                if process.poll() is not None:
                    returncode = process.poll()
                    logging.warning(f"{name} 进程已退出，返回码: {returncode}")
                    processes.remove(proc_info)
                    
                    # 尝试重启进程
                    if name == "api_server":
                        logging.info("正在尝试重启API服务器...")
                        new_process = start_api_server(proc_info.get("port", 8000))
                        if new_process:
                            logging.info("API服务器重启成功")
                    elif name == "print_service":
                        logging.info("正在尝试重启打印服务...")
                        new_process = start_print_service()
                        if new_process:
                            logging.info("打印服务重启成功")
                
                # 读取进程的输出
                while True:
                    output = process.stdout.readline()
                    if output:
                        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                        print(f"[{timestamp}] [{name}] {output.strip()}")
                    else:
                        break
            
            time.sleep(0.1)
    except KeyboardInterrupt:
        logging.info("接收到中断信号，停止所有服务...")
        stop_all_processes()

def stop_all_processes():
    """停止所有进程"""
    for proc_info in processes:
        process = proc_info["process"]
        name = proc_info["name"]
        logging.info(f"正在停止 {name} 进程 (PID: {process.pid})...")
        
        try:
            if os.name == 'nt':  # Windows
                os.kill(process.pid, signal.CTRL_BREAK_EVENT)
            else:  # Linux/Mac
                process.terminate()
            
            # 等待进程结束
            process.wait(timeout=5)
            logging.info(f"{name} 进程已停止")
        except subprocess.TimeoutExpired:
            logging.warning(f"{name} 进程未能及时停止，强制终止")
            process.kill()
        except Exception as e:
            logging.error(f"停止 {name} 进程时出错: {str(e)}")

def parse_arguments():
    """解析命令行参数"""
    parser = argparse.ArgumentParser(description="云打印系统启动脚本")
    parser.add_argument("--api-only", action="store_true", help="仅启动API服务")
    parser.add_argument("--print-only", action="store_true", help="仅启动打印服务")
    parser.add_argument("--port", type=int, default=8000, help="API服务端口，默认为8000")
    return parser.parse_args()

def main():
    """主函数"""
    # 设置环境
    setup_environment()
    
    # 解析命令行参数
    args = parse_arguments()
    
    # 启动服务
    try:
        if args.api_only:
            api_process = start_api_server(args.port)
            if not api_process:
                sys.exit(1)
        elif args.print_only:
            print_process = start_print_service()
            if not print_process:
                sys.exit(1)
        else:
            # 只启动API服务
            api_process = start_api_server(args.port)
            if not api_process:
                sys.exit(1)
            
            # 打印功能现在通过API调用，不再需要单独的打印服务
            logging.info("打印功能将通过API手动触发，不再启动独立的打印服务")
        
        # 监控进程状态
        monitor_processes()
    except KeyboardInterrupt:
        logging.info("接收到中断信号，正在停止服务...")
        stop_all_processes()
    except Exception as e:
        logging.error(f"运行时发生错误: {str(e)}")
        stop_all_processes()
        sys.exit(1)
    finally:
        logging.info("云打印系统已停止")

if __name__ == "__main__":
    main() 